<?php 
/*
* Fetch information from amazon alexa
*/
include_once("config.inc");
include_once("connection_pool.php");

class alexa_info{
	
	const SERVICE_ENDPOINT = "http://awis.amazonaws.com?";
	const AWS_NAMESPACE = "http://awis.amazonaws.com/doc/2005-07-11";
	private static $RESPONSE_GROUP = array(array("action"=>"UrlInfo","RESPONSE_GROUP"=>"SiteData"), 
															 array("action"=>"UrlInfo","RESPONSE_GROUP"=>"TrafficData"),
															 array("action"=>"UrlInfo","RESPONSE_GROUP"=>"LinksInCount"),
															 array("action"=>"UrlInfo","RESPONSE_GROUP"=>"Speed"),
															 array("action"=>"UrlInfo","RESPONSE_GROUP"=>"Related"));
	private $site_url; 
	private $response_group;
	private $days;
	private $aws_url;
	private $result;
	private $result_array;
	private $mysql;

	function __construct($site_url){
		$this->site_url = $site_url;
		$this->mysql = connection_pool::connection();
	}
	
	// Retreve information from AWS
	public function make_URL_info_request($action,$response_group,$days=0){
		if($days<1) $this->days = 31;
		else	$this->days = $days;    
		$this->response_group = $response_group; 
		$this->generate_url($action,$response_group); 
		
		$this->result = $this->make_http_request($this->aws_url);
		/*
		$filename = "../saved_url_info/Ipad/".$response_group."_".urlencode($this->site_url).".xml";
		$handle = fopen($filename, "w+");
		fwrite($handle, $this->result);
		fclose($handle);
		*/
		/*
		$filename = "../saved_url_info/Ipad/".$response_group."_".urlencode($this->site_url).".xml";
		$handle = fopen($filename, "r");
		$this->result = fread($handle, filesize($filename));
		fclose($handle);
		*/
		
	}	
	
	// Retreve information from AWS
	public function get_all_info(){
		$final_result = array();
		foreach(alexa_info::$RESPONSE_GROUP as $request){
			$action = $request['action'];
			$response_group = $request['RESPONSE_GROUP'];	
			$this->make_URL_info_request($action,$response_group);  
			$final_result[$response_group] = $this->get_result_array();
		}
		return $final_result;
	}	
	
	public function get_all_info_json(){
		return json_encode($this->get_all_info());	
	}
	
	
	// Returns the AWS url to get AWIS information for the given site
	private function generate_url($action,$response_group) {
        $timestamp =  alexa_info::generate_timestamp();
        $site_enc = urlencode($this->site_url);
        $timestamp_enc = urlencode($timestamp);
        $signature_enc = urlencode(alexa_info::calculate_RFC2104HMAC($action . $timestamp, SECRET_ACCESS_KEY));
		switch($action){
			case "UrlInfo":
			/*The URL Information Action provides information about websites. Examples of this 
			  information may include data on how popular a site is, sites that are related, 
			  and contact information for the owner of a site.*/
				$this->aws_url = self::SERVICE_ENDPOINT
        				. "AWSAccessKeyId=".ACCESS_KEY_ID
        				. "&Action=UrlInfo"
        				. "&ResponseGroup=".$response_group
        				. "&Timestamp=$timestamp_enc"
        				. "&Signature=$signature_enc"
        				. "&Url=$site_enc";
        		break;				
			case "TrafficHistory":
			/*The TrafficHistory action returns the daily Alexa Traffic Rank, Reach per Million Users,
			  and Unique Page Views per Million Users for each day since June 2007. This same data is
			  used to produce the traffic graphs found on alexa.com.*/
				$this->aws_url = self::SERVICE_ENDPOINT
        				. "AWSAccessKeyId=".ACCESS_KEY_ID
        				. "&Action=TrafficHistory"
        				. "&ResponseGroup=History"
        				. "&Timestamp=$timestamp_enc"
        				. "&Signature=$signature_enc"
        				. "&Url=$site_enc"
        				. "&Range=7"
        				. "&Start=".$this->getTime();

        		break;
        		
			case "SitesLinkingIn":
			/*The Sites Linking In action returns a list of web sites linking to a given web site. 
			  Within each domain linking into the web site, only a single link - the one with the 
		 	  highest page-level traffic - is returned. The data is updated once every two months.*/
				$this->aws_url = self::SERVICE_ENDPOINT
        				. "AWSAccessKeyId=".ACCESS_KEY_ID
        				. "&Action=SitesLinkingIn"
        				. "&ResponseGroup=SitesLinkingIn"
        				. "&Timestamp=$timestamp_enc"
        				. "&Signature=$signature_enc"
        				. "&Url=$site_enc"
        				. "&Count=10"
        				. "&Start=0";
        		break;				
			default: break;

		}
	}	

	// Make an http request to the specified URL and return the result
	private static function make_http_request($url){

       $ch = curl_init($url);
       curl_setopt($ch, CURLOPT_TIMEOUT, 4);
	   curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
       $result = curl_exec($ch);
       curl_close($ch);
       return $result;
	}
	
	// Calculate signature using HMAC: http://www.faqs.org/rfcs/rfc2104.html
	private static function calculate_RFC2104HMAC ($data, $key) {
    	return base64_encode (
        	pack("H*", sha1((str_pad($key, 64, chr(0x00))
        	^(str_repeat(chr(0x5c), 64))) .
        	pack("H*", sha1((str_pad($key, 64, chr(0x00))
        	^(str_repeat(chr(0x36), 64))) . $data))))
     	);
	}

	// Timestamp format: yyyy-MM-dd'T'HH:mm:ss.SSS'Z'
	private static function generate_timestamp () {
    	return gmdate("Y-m-d\TH:i:s.\\0\\0\\0\\Z", time());
	}
	
	// Return the start time for history and siteslinkingin actions
	private function getTime(){
		$month = $this->days*24*60*60;
		return urlencode(date("Ymd", time()-$month));
	}
	
	public function get_result_json(){
		return json_encode($this->get_result_array());
	}
	
	public function get_result_array(){ 
		if($this->check_db()){
			return json_decode(stripslashes($this->get_result_from_db()),true);
		}
		if($this->result!="")
			$xml = simplexml_load_string($this->result);
		else return array();
		switch($this->response_group){
			case "SitesLinkingIn": 
				$result = $this->get_sites_linking_in($xml);
				break;
			case "History":
				$result = $this->get_history($xml);
				break;
			case "LinksInCount":
				$result = $this->get_links_in_count($xml);	
				break;	
			case "Related":
				$result = $this->get_related($xml);	
				break;
			case "SiteData":
				$result = $this->get_site_data($xml);	
				break;
			case "TrafficData":
				$result = $this->get_traffic_data($xml);	
				break;
			case "Speed":
				$result = $this->get_speed_data($xml);
				break;
			default: $result = array(); break;
			
		}
		$this->update_db($result);	
		return $result;
	}
	
	
	private function check_db(){
		$time = date('Y-m-d',time());
		$arr = array("url LIKE '".urlencode($this->site_url)."'", "expired_date > '".$time."'", $this->response_group." <> ''");
		return $this->mysql->if_record_exist(URL_TABLE,$arr);
	}
	
	private function get_result_from_db(){
		$result = $this->mysql->select(URL_TABLE,array($this->response_group),array("url"=>urlencode($this->site_url)));
		//echo $result[0][$this->response_group]."<br>";
		return $result[0][$this->response_group];
	}
	
	private function update_db($result){
		$arr = array("url LIKE '".urlencode($this->site_url)."'");
		$time = date('Y-m-d',time()+7*24*60*60);
		if($this->mysql->if_record_exist(URL_TABLE,$arr)){
			$this->mysql->update(URL_TABLE, array($this->response_group=>addslashes(json_encode($result))), array("url"=>urlencode($this->site_url)));	
		}
		else{
			$arr = array("url"=>urlencode($this->site_url),
						 "expired_date"=>$time,
						 $this->response_group=>addslashes(json_encode($result))
						);
			$this->mysql->insert_data(URL_TABLE,$arr);
		}
	}
	
	
	public function get_speed_data($xml){
		$result = array();
		foreach($xml->children(self::AWS_NAMESPACE) as $entry){
			$site = $entry->UrlInfoResult->Alexa->ContentData;
			$result = array("MedianLoadTime"=>(string)$site->Speed->MedianLoadTime, "Percentile"=>(string)$site->Speed->Percentile);	
		}			
		return $result;
	}
	
	public function get_sites_linking_in($xml){
		$result = array();
		foreach($xml->children(self::AWS_NAMESPACE) as $entry){
				foreach($entry->SitesLinkingInResult->Alexa->SitesLinkingIn->children(self::AWS_NAMESPACE) as $site){
					array_push($result, array("Title"=>(string)$site->Title, "Url"=>(string)$site->Url));
				}	
		}			
		return $result;
	}
	
	
	public function get_site_data($xml){
		$result = array();
		foreach($xml->children(self::AWS_NAMESPACE) as $entry){
				$site = $entry->UrlInfoResult->Alexa->ContentData->children(self::AWS_NAMESPACE);
				$result = array("Title"=>(string)$site->SiteData->Title, "Description"=>(string)$site->SiteData->Description, "OnlineSince"=>(string)$site->SiteData->OnlineSince);

		}			
		return $result;
	}
	

	public function get_traffic_data($xml){
		$result = array();
		$xml = simplexml_load_string($this->result);
		foreach($xml->children(self::AWS_NAMESPACE) as $entry){
			$site = $entry->UrlInfoResult->Alexa->TrafficData->children(self::AWS_NAMESPACE);
			$result["Rank"] = (string)$site->Rank;
			$result["Usage"] = array();
			foreach($site->UsageStatistics->children(self::AWS_NAMESPACE) as $usage){
						$tuple = array("TimeRange"=>(string)$usage->TimeRange->children(self::AWS_NAMESPACE),
										 			 "Rank" => array("Value" => (string)$usage->Rank->Value,"Delta" => (string)$usage->Rank->Delta),
										 			 "Reach" =>  array("Value" => (string)$usage->Reach->PerMillion->Value,"Delta" => (string)$usage->Reach->PerMillion->Delta),
										 			 "PageViews" => array("Value"=> (string)$usage->PageViews->PerMillion->Value, "Delta" => (string)$usage->PageViews->PerMillion->Delta)
										 );	
						array_push($result['Usage'], $tuple);
			}
		}			
		return $result;
	}	
	
	
	public function get_related($xml){
		$result = array();
		$result2 = array();
		foreach($xml->children(self::AWS_NAMESPACE) as $entry){
			if(count($entry->UrlInfoResult->Alexa->Related->RelatedLinks)>0){
				foreach($entry->UrlInfoResult->Alexa->Related->RelatedLinks->children(self::AWS_NAMESPACE) as $site){
					array_push($result, array("Title"=>(string)$site->Title, "Url"=>(string)$site->DataUrl));
				}
			}
			if(count($entry->UrlInfoResult->Alexa->Related->Categories)>0){
					foreach($entry->UrlInfoResult->Alexa->Related->Categories->children(self::AWS_NAMESPACE) as $cate){
						array_push($result2, array("Title"=>(string)$cate->Title, "AbsolutePath"=>(string)$cate->AbsolutePath));
				}	
			}
		}			
		return array("sites"=>$result, "categories"=>$result2);
	}
	
	public function get_links_in_count($xml){
		$result = array();
		foreach($xml->children(self::AWS_NAMESPACE) as $entry){
			$t = $entry->UrlInfoResult->Alexa->ContentData->LinksInCount;
			$result = array("LinksInCount"=>(string)$t);
		}			
		return $result;
	}
	
	public function get_history($xml){
		$result = array();
		foreach($xml->children(self::AWS_NAMESPACE) as $entry){
				foreach($entry->TrafficHistoryResult->Alexa->TrafficHistory->HistoricalData->children(self::AWS_NAMESPACE) as $day){
					array_push($result, array("Date"=> (string)$day->Date,
																	  "PageViews"=>array("PerMillion"=> (string)$day->PageViews->PerMillion,
																	  										"PerUser"=> (string)$day->PageViews->PerUser),
																	  "Rank" => (string)$day->Rank,
																	  "Reach"=> (string)$day->Reach->PerMillion										
																	 )
									  );
				}	
		}			
		return $result;
	}
	
	public function get_result_xml(){
		return $this->result;
	}
	
	

}


?>